package com.yanhui.api.ai;

import cn.xsshome.taip.nlp.TAipNlp;
import com.baidu.aip.speech.AipSpeech;
import com.baidu.aip.speech.TtsResponse;
import com.baidu.aip.util.Util;
import com.yanhui.utils.ApiAccount;
import javazoom.spi.mpeg.sampled.file.MpegAudioFileReader;
import net.sf.json.JSONObject;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * @Description 语音人工智能
 * @Author yanhui
 * @Date 2018-11-29 18:24
 */
public class SpeechApi {

    public static void main(String[] args) throws Exception {
        String voiceRealPath = "C:\\Users\\admin\\Desktop\\定位精准-北斗厘米级定位服务来临.mp4";
//        String result = speechTranslate(voiceRealPath);
//        System.out.println(result);
//
        String videoOutputPath =voiceRealPath+"12.mp4";
        String videoOutputPath2 =voiceRealPath+"13.mp4";
//        convertMP32PCM(voiceRealPath, pcmRealPath);
//        getPcm(pcmRealPath);

        //wav转文字
//        String filePath = "C:\\Users\\admin\\Desktop\\定位精准-北斗厘米级定位服务来临.mp4";
//        String wavRealPath ="C:\\Users\\admin\\Desktop\\22.mp3";

//        String pcmRealPath = "C:\\Users\\admin\\Desktop\\new.pcm";
//        convertMP32PCM(wavRealPath, pcmRealPath);
//        getPcmFromMp3(wavRealPath,pcmRealPath); //不行
//        getPcm(pcmRealPath); //不行
//        speechTranslate(wavRealPath);
//        int temCount = 2;
//        _fileUtils.getSplitFile(filePath, temCount );


//        getPartFromVideo(voiceRealPath,"00:00:00","00:00:30", videoOutputPath);
//        getPartFromVideo(voiceRealPath,"00:00:30","00:01:10", videoOutputPath2);
        //1、截取

        //2、转mp3
        String a = "C:\\Users\\admin\\Desktop\\定位精准-北斗厘米级定位服务来临.mp412.mp3";
//        getVoiceFromVideo(a, "C:\\Users\\admin\\Desktop\\定位精准-北斗厘米级定位服务来临.mp412.mp3"); //获取音频
//        convertMP32PCM(voiceRealPath, pcmRealPath);
        //3.1、MP3语音转文字
//        speechTranslate(a);
        //3.2、MP3转pcm 百度转
//        convertMP32PCM(a,a+"new.pcm");
//        getPcm(a+"new.pcm"); //不行
        speechTranslate(a);
    }

    //截取视频
    private static void getPartFromVideo(String videoRealPath, String starTime, String endTime,
                                         String videoOutputPath){
        List<String> commend = new ArrayList<String>();
        commend.add(FFMPEG_EXE);
        commend.add("-i");//截取视频段
        commend.add(videoRealPath);
        commend.add("-ss");
        commend.add(starTime);//start
        commend.add("-t");
        commend.add(endTime);//end
        commend.add("-acodec");
        commend.add("copy");
        commend.add("-vcodec");
        commend.add("copy");
        commend.add(videoOutputPath);
        try {
            ProcessBuilder builder = new ProcessBuilder();
            builder.command(commend);
            builder.redirectErrorStream(true);
            Process process = builder.start();
            process.waitFor();//等待进程执行结束
            process.destroy();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 将一个mp4的视频转为mp3，将语音再转为文字
     * @param filePath
     * @return
     * @throws Exception
     */
    public static String mp4ToText(String filePath) throws Exception {
        String videoRealPath = filePath;
        String voiceRealPath =filePath+".mp3";
        String pcmRealPath =filePath+".pcm";
        String pcmRealPath1 =filePath+"_0.pcm";
        String pcmRealPath2 =filePath+"_1.pcm";
//        getVoiceFromVideo(videoRealPath, voiceRealPath); //获取音频
//        convertMP32PCM(voiceRealPath, pcmRealPath);
        int temCount = 2;
        String tempFile = pcmRealPath;
//        _fileUtils.getSplitFile(tempFile, temCount );
        String result1 = getPcm(pcmRealPath1);
        String result2 = getPcm(pcmRealPath2);
        return result1+result2;
    }

    private static final String FFMPEG_EXE = "D:\\DesignSoftware\\ffmpeg-20181023-c2ac3b8-win64-static\\bin\\ffmpeg.exe";
    private static void getVoiceFromVideo(String videoRealPath, String voiceRealPath) {
        List<String> commend =new java.util.ArrayList<String>();
        commend.add(FFMPEG_EXE);
        commend.add("-i");
        commend.add(videoRealPath);
        commend.add("-vn");
        commend.add("-ar");
        commend.add("44100");
        commend.add("-ac");
        commend.add("2");
        commend.add("-ab");
        commend.add("192");
        commend.add("-f");
        commend.add("mp3");
        commend.add(voiceRealPath);
        try {
            ProcessBuilder builder = new ProcessBuilder();
            builder.command(commend);
            builder.redirectErrorStream(true);
            System.out.println("视频语音分离开始...");
            Process process =builder.start();
            process.waitFor();//等待进程执行结束
            System.out.println("视频语音分离完成...");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("视频语音分离失败！");
        }

    }

    private static void getPcmFromMp3(String mp3RealPath, String pcmRealPath) {
        List<String> commend =new java.util.ArrayList<String>();
        //ffmpeg -y  -i WeChat_20180524094805.mp3  -acodec pcm_s16le -f s16le -ac 1 -ar 16000 16k.pcm
        commend.add(FFMPEG_EXE);
        commend.add("-i");
        commend.add(mp3RealPath);
        commend.add("-f");
        commend.add("s16le");
        commend.add("-ar");
        commend.add("16000");
        commend.add("-ac");
        commend.add("1");
        commend.add("-acodec");
        commend.add("pcm_s16be");
        commend.add(pcmRealPath);
        try {
            ProcessBuilder builder = new ProcessBuilder();
            builder.command(commend);
            builder.redirectErrorStream(true);
            System.out.println("视频语音分离开始...");
            Process process =builder.start();
            process.waitFor();//等待进程执行结束
            System.out.println("视频语音分离完成...");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("视频语音分离失败！");
        }

    }

    /**
     * MP3转换PCM文件方法
     *
     * @param mp3filepath
     *            原始文件路径
     * @param pcmfilepath
     *            转换文件的保存路径
     * @throws Exception
     */
    public static void convertMP32PCM(String mp3filepath, String pcmfilepath) throws Exception {
        AudioInputStream audioInputStream = getPcmAudioInputStream(mp3filepath);
        AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, new File(pcmfilepath));
    }

    private static AudioInputStream getPcmAudioInputStream(String mp3filepath) {
        File mp3 = new File(mp3filepath);
        AudioInputStream audioInputStream = null;
        AudioFormat targetFormat ;
        try {
            MpegAudioFileReader mp = new MpegAudioFileReader();
            AudioInputStream in = mp.getAudioInputStream(mp3);
            AudioFormat baseFormat = in.getFormat();
            targetFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16,
                    baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false);
            audioInputStream = AudioSystem.getAudioInputStream(targetFormat, in);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return audioInputStream;
    }

    /**
     * 语音翻译：将语音转为文字信息
     * @return
     */
    public static String speechTranslate(String filePath) throws Exception {
        TAipNlp aipNlp = new TAipNlp(ApiAccount.TENCENT_APP_ID_AI+"", ApiAccount.TENCENT_APP_KEY_AI);
        String session = new Date().getTime() / 1000 + "";
        String result = aipNlp.nlpSpeechTranslate(8, 0, 1, session, filePath, "zh", "en");//语音翻译
        System.out.println(result);
        JSONObject obj1 = JSONObject.fromObject(result);
        JSONObject obj2 = JSONObject.fromObject(obj1.get("data").toString());
        result = obj2.get("source_text").toString();
        result = result.replaceAll( "[\\p{P}+~$`^=|<>～｀＄＾＋＝｜＜＞￥×]" , "");
        return result;
    }

    private static AipSpeech getAipSpeech() {
        AipSpeech client = new AipSpeech(ApiAccount.BAIDU_APP_ID, ApiAccount.BAIDU_API_KEY, ApiAccount.BAIDU_SECRET_KEY);
        client.setConnectionTimeoutInMillis(2000);
        client.setSocketTimeoutInMillis(60000);
        return client;
    }

    /**
     * 语音识别　pcm
     * 将语音转为文字信息
     * @param fileName
     * <input type="file" accept="audio/*" capture="microphone">
     * @return
     */
    public static String getPcm(String fileName) throws Exception {
        AipSpeech client = getAipSpeech();
        org.json.JSONObject res = client.asr(fileName, "pcm", 16000, null);
        System.out.println(res.toString());
        Object obj = res.get("result");
        return obj.toString().replace("[\"", "").replace("，\"]", "");

    }

    /**
     * 语音合成 mp3
     * 将文字转为语音输出
     * @param text 文字
     * @param output 输出mp3
     */
    public static void getVoice(String text, String output) {
        AipSpeech client = getAipSpeech();
        //发音人选择, 0为女声，1为男声，
        //3为情感合成-度逍遥，4为情感合成-度丫丫，默认为普通女
        // www.yanhui.fun
        HashMap<String, Object> options = new HashMap<String, Object>();
//        options.put("spd", "5");
//        options.put("pit", "5");
        options.put("per", "1");
        TtsResponse res = client.synthesis(text, "zh", 1, options);
        byte[] data = res.getData();
        org.json.JSONObject res1 = res.getResult();
        if (data != null) {
            try {
                Util.writeBytesToFileSystem(data, output);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (res1 != null) {
            System.out.println(res1.toString());
        }
    }
}
